package com.example.scribe;

import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.TerminalNode;

/**
 * 负责将ANTLR ParseTree转换为SyntaxNode的转换器
 * 这是重构后的简化版本，将原来的巨大convert方法分解为更小的专门方法
 */
public class ParseTreeConverter {
    
    /**
     * 将ParseTree转换为SyntaxNode
     */
    public SyntaxNode convert(ParseTree tree) {
        if (tree instanceof TerminalNode) {
            return convertTerminalNode((TerminalNode) tree);
        }
        
        if (tree instanceof ParserRuleContext) {
            return convertParserRuleContext((ParserRuleContext) tree);
        }
        
        // 默认处理
        return convertGeneric(tree);
    }
    
    /**
     * 转换终端节点
     */
    private SyntaxNode convertTerminalNode(TerminalNode node) {
        Token token = node.getSymbol();
        String tokenName = getTokenName(token);
        String text = node.getText();
        return new SyntaxNode("Terminal:" + tokenName, text);
    }
    
    /**
     * 获取Token名称
     */
    private String getTokenName(Token token) {
        if (token == null) return "EOF";
        
        // 使用反射获取词汇表，避免直接依赖生成的类
        try {
            Class<?> lexerClass = Class.forName("com.example.scribe.parser.ScribeLexer");
            Object vocabulary = lexerClass.getField("VOCABULARY").get(null);
            String name = (String) vocabulary.getClass()
                .getMethod("getSymbolicName", int.class)
                .invoke(vocabulary, token.getType());
            return name != null ? name : "UNKNOWN";
        } catch (Exception e) {
            return "UNKNOWN";
        }
    }
    
    /**
     * 转换解析规则上下文
     */
    private SyntaxNode convertParserRuleContext(ParserRuleContext ctx) {
        String ruleName = getRuleName(ctx);
        
        // 根据规则名称选择特定的转换方法
        return switch (ruleName) {
            case "if_stmt" -> convertIfStatement(ctx);
            case "while_stmt" -> convertWhileStatement(ctx);
            case "variable_decl" -> convertVariableDecl(ctx);
            case "function_decl" -> convertFunctionDecl(ctx);
            case "lambda_expr" -> convertLambdaExpr(ctx);
            case "call" -> convertCall(ctx);
            case "range_expr" -> convertRangeExpr(ctx);
            case "shift" -> convertShift(ctx);
            default -> convertGenericRule(ctx, ruleName);
        };
    }
    
    /**
     * 获取规则名称
     */
    private String getRuleName(ParserRuleContext ctx) {
        try {
            Class<?> parserClass = Class.forName("com.example.scribe.parser.ScribeParser");
            String[] ruleNames = (String[]) parserClass.getField("ruleNames").get(null);
            return ruleNames[ctx.getRuleIndex()];
        } catch (Exception e) {
            return ctx.getClass().getSimpleName();
        }
    }
    
    /**
     * 转换if语句
     */
    private SyntaxNode convertIfStatement(ParserRuleContext ctx) {
        SyntaxNode node = new SyntaxNode("IfStatement", ctx.getText());
        boolean hasConsequent = false;
        
        for (int i = 0; i < ctx.getChildCount(); i++) {
            ParseTree child = ctx.getChild(i);
            if (child instanceof TerminalNode) {
                String text = child.getText();
                if ("else".equals(text.toLowerCase())) {
                    continue; // Skip 'else' keyword
                }
            } else if (child instanceof ParserRuleContext) {
                String childRuleName = getRuleName((ParserRuleContext) child);
                if ("expression".equals(childRuleName)) {
                    SyntaxNode condWrapper = new SyntaxNode("Condition", "");
                    condWrapper.addChild(convert(child));
                    node.addChild(condWrapper);
                } else if ("block_stmt".equals(childRuleName)) {
                    if (hasConsequent) {
                        SyntaxNode altWrapper = new SyntaxNode("Alternative", "");
                        altWrapper.addChild(convert(child));
                        node.addChild(altWrapper);
                    } else {
                        SyntaxNode consWrapper = new SyntaxNode("Consequent", "");
                        consWrapper.addChild(convert(child));
                        node.addChild(consWrapper);
                        hasConsequent = true;
                    }
                }
            }
        }
        return node;
    }
    
    /**
     * 转换while语句
     */
    private SyntaxNode convertWhileStatement(ParserRuleContext ctx) {
        SyntaxNode node = new SyntaxNode("WhileStatement", ctx.getText());
        
        for (int i = 0; i < ctx.getChildCount(); i++) {
            ParseTree child = ctx.getChild(i);
            if (!(child instanceof TerminalNode)) {
                String childRuleName = getRuleName((ParserRuleContext) child);
                if ("expression".equals(childRuleName)) {
                    SyntaxNode condWrapper = new SyntaxNode("Condition", "");
                    condWrapper.addChild(convert(child));
                    node.addChild(condWrapper);
                } else if ("block_stmt".equals(childRuleName)) {
                    SyntaxNode bodyWrapper = new SyntaxNode("Body", "");
                    bodyWrapper.addChild(convert(child));
                    node.addChild(bodyWrapper);
                }
            }
        }
        return node;
    }
    
    /**
     * 转换变量声明
     */
    private SyntaxNode convertVariableDecl(ParserRuleContext ctx) {
        SyntaxNode node = new SyntaxNode("VariableDecl", ctx.getText());
        
        for (int i = 0; i < ctx.getChildCount(); i++) {
            ParseTree child = ctx.getChild(i);
            if (child instanceof TerminalNode) {
                Token token = ((TerminalNode) child).getSymbol();
                String tokenName = getTokenName(token);
                if ("LET".equals(tokenName) || "CONST".equals(tokenName)) {
                    node.addChild(new SyntaxNode("Kind", ((TerminalNode) child).getText()));
                }
            } else if (child instanceof ParserRuleContext) {
                String childRuleName = getRuleName((ParserRuleContext) child);
                if ("identifier".equals(childRuleName)) {
                    node.addChild(new SyntaxNode("Identifier", child.getText()));
                } else if ("type_annotation".equals(childRuleName)) {
                    extractTypeFromAnnotation(node, (ParserRuleContext) child);
                } else if ("expression".equals(childRuleName)) {
                    SyntaxNode exprNode = new SyntaxNode("expression", child.getText());
                    exprNode.addChild(convert(child));
                    node.addChild(exprNode);
                }
            }
        }
        return node;
    }
    
    /**
     * 从类型注解中提取类型
     */
    private void extractTypeFromAnnotation(SyntaxNode parentNode, ParserRuleContext typeAnnotation) {
        for (int j = 0; j < typeAnnotation.getChildCount(); j++) {
            ParseTree typeChild = typeAnnotation.getChild(j);
            if (typeChild instanceof ParserRuleContext) {
                String typeChildName = getRuleName((ParserRuleContext) typeChild);
                if ("primitive_type".equals(typeChildName) || "identifier".equals(typeChildName)) {
                    parentNode.addChild(new SyntaxNode("Type", typeChild.getText()));
                    break;
                }
            }
        }
    }
    
    /**
     * 转换函数声明
     */
    private SyntaxNode convertFunctionDecl(ParserRuleContext ctx) {
        SyntaxNode node = new SyntaxNode("FunctionDecl", ctx.getText());
        
        for (int i = 0; i < ctx.getChildCount(); i++) {
            ParseTree child = ctx.getChild(i);
            if (child instanceof ParserRuleContext) {
                ParserRuleContext childCtx = (ParserRuleContext) child;
                String childRuleName = getRuleName(childCtx);
                
                switch (childRuleName) {
                    case "identifier" -> node.addChild(new SyntaxNode("Name", childCtx.getText()));
                    case "param_list" -> node.addChild(convertParamList(childCtx));
                    case "type_annotation" -> {
                        SyntaxNode ret = new SyntaxNode("ReturnType", "");
                        extractTypeFromAnnotation(ret, childCtx);
                        node.addChild(ret);
                    }
                    case "block_stmt" -> {
                        node.addChild(new SyntaxNode("Body", ""));
                        node.addChild(convert(childCtx));
                    }
                }
            }
        }
        return node;
    }
    
    /**
     * 转换参数列表
     */
    private SyntaxNode convertParamList(ParserRuleContext paramListCtx) {
        SyntaxNode params = new SyntaxNode("Params", "");
        
        for (int j = 0; j < paramListCtx.getChildCount(); j++) {
            ParseTree param = paramListCtx.getChild(j);
            if (param instanceof ParserRuleContext) {
                ParserRuleContext paramCtx = (ParserRuleContext) param;
                String paramRuleName = getRuleName(paramCtx);
                if ("param".equals(paramRuleName)) {
                    params.addChild(convertParam(paramCtx));
                }
            }
        }
        return params;
    }
    
    /**
     * 转换单个参数
     */
    private SyntaxNode convertParam(ParserRuleContext paramCtx) {
        SyntaxNode paramNode = new SyntaxNode("Param", "");
        
        for (int k = 0; k < paramCtx.getChildCount(); k++) {
            ParseTree part = paramCtx.getChild(k);
            if (part instanceof ParserRuleContext) {
                ParserRuleContext partCtx = (ParserRuleContext) part;
                String partName = getRuleName(partCtx);
                if ("identifier".equals(partName)) {
                    paramNode.addChild(new SyntaxNode("Identifier", partCtx.getText()));
                } else if ("type_annotation".equals(partName)) {
                    extractTypeFromAnnotation(paramNode, partCtx);
                }
            }
        }
        return paramNode;
    }
    
    /**
     * 转换Lambda表达式
     */
    private SyntaxNode convertLambdaExpr(ParserRuleContext ctx) {
        SyntaxNode node = new SyntaxNode("Lambda", ctx.getText());
        
        for (int i = 0; i < ctx.getChildCount(); i++) {
            ParseTree child = ctx.getChild(i);
            if (child instanceof ParserRuleContext) {
                ParserRuleContext childCtx = (ParserRuleContext) child;
                String childRuleName = getRuleName(childCtx);
                
                switch (childRuleName) {
                    case "param_list" -> node.addChild(convertParamList(childCtx));
                    case "type_annotation" -> node.addChild(new SyntaxNode("ReturnType", childCtx.getText()));
                    case "expression" -> node.addChild(new SyntaxNode("BodyExpr", childCtx.getText()));
                    case "block_stmt" -> {
                        node.addChild(new SyntaxNode("Body", ""));
                        node.addChild(convert(childCtx));
                    }
                }
            }
        }
        return node;
    }
    
    /**
     * 转换函数调用
     */
    private SyntaxNode convertCall(ParserRuleContext ctx) {
        SyntaxNode node = new SyntaxNode("Call", ctx.getText());
        SyntaxNode callee = null;
        SyntaxNode argsNode = new SyntaxNode("Args", "");
        
        for (int i = 0; i < ctx.getChildCount(); i++) {
            ParseTree child = ctx.getChild(i);
            if (child instanceof ParserRuleContext) {
                ParserRuleContext childCtx = (ParserRuleContext) child;
                String childRuleName = getRuleName(childCtx);
                if ("primary".equals(childRuleName)) {
                    callee = convert(childCtx);
                } else if ("arg_list".equals(childRuleName)) {
                    convertArgList(childCtx, argsNode);
                }
            }
        }
        
        if (callee != null) node.addChild(callee);
        if (!argsNode.children().isEmpty()) node.addChild(argsNode);
        return node;
    }
    
    /**
     * 转换参数列表
     */
    private void convertArgList(ParserRuleContext argListCtx, SyntaxNode argsNode) {
        for (int j = 0; j < argListCtx.getChildCount(); j++) {
            ParseTree arg = argListCtx.getChild(j);
            if (arg instanceof ParserRuleContext) {
                String argRuleName = getRuleName((ParserRuleContext) arg);
                if ("expression".equals(argRuleName) || "assignment".equals(argRuleName) || "conditional".equals(argRuleName)) {
                    argsNode.addChild(convert(arg));
                }
            }
        }
    }
    
    /**
     * 转换shift表达式 (<<, >>, >>>)
     * 语法: multiplication ( ('<<' | '>>' | '>>>') multiplication )*
     */
    private SyntaxNode convertShift(ParserRuleContext ctx) {
        SyntaxNode node = new SyntaxNode("shift", ctx.getText());
        
        // shift规则: multiplication ( ('<<' | '>>' | '>>>') multiplication )*
        // 第一个子节点应该是 multiplication
        // 后续可能是: Terminal (操作符), multiplication (右操作数)
        for (int i = 0; i < ctx.getChildCount(); i++) {
            ParseTree child = ctx.getChild(i);
            if (child instanceof ParserRuleContext) {
                // 这是 multiplication 节点
                node.addChild(convert(child));
            } else if (child instanceof TerminalNode) {
                // 这是操作符 Terminal 节点 (<<, >>, >>>)
                node.addChild(convert(child));
            }
        }
        
        return node;
    }
    
    /**
     * 转换范围表达式
     */
    private SyntaxNode convertRangeExpr(ParserRuleContext ctx) {
        SyntaxNode node = new SyntaxNode("RangeExpr", ctx.getText());
        SyntaxNode start = null;
        SyntaxNode end = null;
        String op = null;
        
        for (int i = 0; i < ctx.getChildCount(); i++) {
            ParseTree child = ctx.getChild(i);
            if (child instanceof ParserRuleContext) {
                ParserRuleContext childCtx = (ParserRuleContext) child;
                String childRuleName = getRuleName(childCtx);
                if ("logical_or".equals(childRuleName) || "expression".equals(childRuleName) || "assignment".equals(childRuleName)) {
                    if (start == null) {
                        start = convert(childCtx);
                        // Store the actual expression node, not just text
                        SyntaxNode startWrapper = new SyntaxNode("Start", "");
                        startWrapper.addChild(start);
                        node.addChild(startWrapper);
                    } else if (end == null) {
                        end = convert(childCtx);
                        // Store the actual expression node, not just text
                        SyntaxNode endWrapper = new SyntaxNode("End", "");
                        endWrapper.addChild(end);
                        node.addChild(endWrapper);
                    }
                }
            } else if (child instanceof TerminalNode) {
                String text = child.getText();
                if ("..".equals(text) || "..=".equals(text)) {
                    op = text;
                    node.addChild(new SyntaxNode("Operator", op));
                }
            }
        }
        
        return node;
    }
    
    /**
     * 通用规则转换
     */
    private SyntaxNode convertGenericRule(ParserRuleContext ctx, String ruleName) {
        SyntaxNode node = new SyntaxNode(ruleName, ctx.getText());
        for (int i = 0; i < ctx.getChildCount(); i++) {
            node.addChild(convert(ctx.getChild(i)));
        }
        return node;
    }
    
    /**
     * 通用转换
     */
    private SyntaxNode convertGeneric(ParseTree tree) {
        SyntaxNode node = new SyntaxNode(tree.getClass().getSimpleName(), tree.getText());
        for (int i = 0; i < tree.getChildCount(); i++) {
            node.addChild(convert(tree.getChild(i)));
        }
        return node;
    }
}
